package com.hxzy.common.util;

import cn.hutool.core.util.StrUtil;
import com.hxzy.common.enums.AckCode;
import com.hxzy.common.exception.ServiceException;
import com.hxzy.common.exception.ServiceStringException;
import com.hxzy.common.props.PasswordLockProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

/**
 * @Author wy
 * @Description 密码错误次数锁定账户
 * @Date 2023/8/31 10:27
 * @Version 1.0
 */
@Component
public class PasswordLockUtil {

    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 账户锁定属性
     */
    @Autowired
    private PasswordLockProperties  passwordLockProperties;


    /**
     * 是否启动密码错误次数锁定账户功能
     * @return
     */
    public boolean isPasswordLock(){
       return this.passwordLockProperties.getEnabled();
    }

    /**
     * 密码登录失败(失败次数<最大次数的)
     * @param uniqueValue
     */
    public void logFailedLoginAttempt(String uniqueValue) {
        String key = this.passwordLockProperties.getPwdErrorPrefix() + uniqueValue;

        //redis存储的 pwd:err:admin-1  = 错误次数
        Object attempts = this.redisTemplate.opsForValue().get(key);
        int loginAttempts=1;
        //查询不到key，代表从来没有错过
        if (attempts == null) {
            //设定赋值过期时间，为小时
            this.redisTemplate.opsForValue().set(key, loginAttempts, this.passwordLockProperties.getDurationHour(), TimeUnit.HOURS);
        } else {
            loginAttempts = (int) attempts;
            loginAttempts++;

            this.redisTemplate.opsForValue().set(key, loginAttempts);

            if (loginAttempts >= this.passwordLockProperties.getMaxcount()) {
                //重新赋值过期时间，为分钟
                this.redisTemplate.expire(key,this.passwordLockProperties.getLockedMinutes(),TimeUnit.MINUTES);

                String temp=StrUtil.format(AckCode.ACCOUNT_TEMPORYARY_LOCKING.getMsg(),this.passwordLockProperties.getLockedMinutes()+"");
                throw new ServiceStringException(temp);
            }
        }

        //最终要抛出异常
        AckCode ack=AckCode.ACCOUNT_PASSWORD_TRY;
        String temp=ack.getMsg();
        temp=StrUtil.format(temp,  (this.passwordLockProperties.getMaxcount()-loginAttempts)+"" );
        throw new ServiceStringException(temp);
    }

    /**
     * 账户的密码是否已经超过最大的次数（超过代表锁了）
     * @param uniqueValue
     * @return false 没有被锁定
     */
    public boolean isAccountLocked(String uniqueValue) {
        String key = this.passwordLockProperties.getPwdErrorPrefix() + uniqueValue;
        Object attempts = this.redisTemplate.opsForValue().get(key);
        if (attempts != null) {
            int loginAttempts = (int) attempts;
            if( loginAttempts >= this.passwordLockProperties.getMaxcount()){

                AckCode ackLock=AckCode.ACCOUNT_TEMPORYARY_LOCKING;
                String temp=ackLock.getMsg();
                temp=StrUtil.format(temp,this.passwordLockProperties.getLockedMinutes()+"");
                throw new ServiceStringException(temp);
            }
        }
        return false;
    }




    /**
     * 移出锁定redis的key
     * @param uniqueValue
     */
    public void unlockAccount(String uniqueValue) {
        String key = this.passwordLockProperties.getPwdErrorPrefix() + uniqueValue;
        this.redisTemplate.delete(key);
    }
}
